#include "./decoder.h"
#include "io/winstub.h"

using namespace MiniUI;
using namespace MiniUI::Type;

Decoder::Decoder(const char* szImagePath)
: m_deco(nullptr)
, m_iostub(nullptr)
, m_pRawDecoder(nullptr)
, m_nStatus(DECODE_STATUS_INIT)
{
    m_iostub = new WinStub(szImagePath, IO_READ);
    m_deco = new DecodeFormat();
    memset(m_deco, 0, sizeof(DecodeFormat));
}

Decoder::~Decoder()
{
    if (m_pRawDecoder)
    {
        m_pRawDecoder->FinishDecode(m_deco);
        delete m_pRawDecoder;
    }
    memset(m_deco, 0, sizeof(DecodeFormat));
    m_iostub->Release();
}

DecodeFormat* Decoder::GetDecodeFormat()
{
    return m_deco;
}

#pragma warning(disable:4748)
bool Decoder::ReadImageInfo()
{
    if (m_nStatus != DECODE_STATUS_INIT)
    {
        return false;
    }

    BaseDecoder* pDecoder = nullptr;

    //find image format
    const int nHeaderSize = 8;
    byte pHeader[nHeaderSize];
    uint uRead = m_iostub->Read(pHeader, nHeaderSize);
    int nRead = (int)uRead;
    m_iostub->Seek(-nRead, SEEK_CUR);
    if (uRead < nHeaderSize)
    {
        //do nothing
    }
    else if (PngDecoder::CheckFormat(pHeader, nHeaderSize))
    {
        //png
        pDecoder = new PngDecoder(m_iostub);
    }

    m_pRawDecoder = pDecoder;
    bool bSuc = false;
    if (pDecoder)
    {
        bSuc = pDecoder->ReadImageInfo(m_deco) ? true : false;
    }

    if (bSuc)
    {
        m_nStatus = DECODE_STATUS_READY;
    }
    else
    {
        m_nStatus = DECODE_STATUS_ZOMBIE;
    }
    return bSuc;
}
#pragma warning(default:4748)

bool Decoder::ReadImageFrame()
{
    if (m_nStatus != DECODE_STATUS_READY)
    {
        return false;
    }

    if (!m_deco->pOutBuffer || !m_pRawDecoder)
    {
        return false;
    }

    bool bSuc = m_pRawDecoder->ReadImageFrame(m_deco) ? true : false;

    if (!bSuc)
    {
        m_nStatus = DECODE_STATUS_ZOMBIE;
    }
    return bSuc;
}